home *** CD-ROM | disk | FTP | other *** search
/ DP Tool Club 19 / CD_ASCQ_19_010295.iso / dos / prg / pas / swag / win_os2.swg / 0029_objects > 64K.pas < prev    next >
Pascal/Delphi Source File  |  1994-08-24  |  6KB  |  267 lines

  1. unit BigArray;
  2.  
  3. { This unit contains an objects that allows for the creation of
  4.   arrays larger than 64K.                                       }
  5.  
  6. interface
  7.  
  8. { The ifdefs allow compiling under windows or protected mode }
  9.  
  10. {$ifdef windows}
  11. uses WinTypes, WinProcs, WinAPI;
  12. {$else}
  13. uses WinAPI;
  14. {$endif}
  15.  
  16. const
  17.   SegSize = 65536;                  { Size of a selector }
  18.  
  19. { Our BigArray object will allow us to allocate large chucks of memory
  20.   (>64k) and index our way through the items }
  21. type
  22.   PBigArray = ^TBigArray;
  23.   TBigArray = object
  24.     MemStart : THandle;
  25.     MemOffset : longint;
  26.     MemSize : longint;
  27.     MaxItems : longint;
  28.     ItemSize : longint;
  29.     constructor Init(NoItems : longint; Size : Word);
  30.     destructor Done; virtual;
  31.     procedure PutData(var Item; Index : longint); virtual;
  32.     procedure GetData(var Item; Index : longint); virtual;
  33.     procedure Resize(NoItems : longint); virtual;
  34.     function GetMeMSize : longint; virtual;
  35.   end;
  36.  
  37. implementation
  38.  
  39. constructor TBigArray.Init(NoItems : longint; Size : Word);
  40. { Determine the size of the memory we need, allocate using the
  41.   GlobalAlloc() routine, and initialize the fields }
  42. begin
  43.   MaxItems := NoItems;
  44.   ItemSize := Size;
  45.   { compute memory size }
  46.   MemSize := MaxItems * ItemSize;
  47.   { allocate the memory }
  48.   MemStart := GlobalAlloc(gmem_Moveable, MemSize);
  49.   { any error? }
  50.   if MemStart = 0 then
  51.     RunError(203);
  52.  
  53.   MemOffset := 0;
  54. end;
  55.  
  56. destructor TBigArray.Done;
  57. { Free up the memory }
  58. begin
  59.   GlobalFree(MemStart);
  60. end;
  61.  
  62. procedure TBigArray.PutData(var Item; Index : longint);
  63. { Put the item in the allocated memory }
  64. var
  65.   Sel, Off : word;
  66.   P : pointer;
  67.   FinishIt : boolean;
  68.   TempItemSize : word;
  69. begin
  70.   if Index >= MaxItems then
  71.     RunError(201);
  72.  
  73.   inc(MemOffset, ItemSize);
  74.  
  75.   { compute index into memory }
  76.   Index := Index * ItemSize;
  77.   { determine the starting selector to access }
  78.   Sel := (Index div SegSize) * SelectorInc + MemStart;
  79.   { determine the offset into that selector }
  80.   Off := Index mod SegSize;
  81.  
  82.   if (SegSize - Off) < ItemSize then begin
  83.     TempItemSize := SegSize - Off;
  84.     FinishIt := true;
  85.   end
  86.   else begin
  87.     TempItemSize := ItemSize;
  88.     FinishIt := false;
  89.   end;
  90.  
  91.   { lock the memory - this only applies to windows }
  92.   GlobalLock(Sel);
  93.  
  94.   { get the pointer value }
  95.   P := ptr(Sel, Off);
  96.  
  97.   { move the data into memory }
  98.   Move(Item, P^, TempItemSize);
  99.  
  100.   { unlock the memory - this only applies to windows }
  101.   GlobalUnLock(Sel);
  102.  
  103.   if FinishIt then begin
  104.     Sel := Sel + SelectorInc;
  105.     Off := 0;
  106.     { lock the memory - this only applies to windows }
  107.     GlobalLock(Sel);
  108.  
  109.     { get the pointer value }
  110.     P := ptr(Sel, Off);
  111.  
  112.     { move the data into memory }
  113.     Move(Item, P^, TempItemSize);
  114.  
  115.     { unlock the memory - this only applies to windows }
  116.     GlobalUnLock(Sel);
  117.   end;
  118. end;
  119.  
  120. procedure TBigArray.GetData(var Item; Index : longint);
  121. { Get the item out of memory }
  122. var
  123.   Sel, Off : word;
  124.   P : pointer;
  125.   FinishIt : boolean;
  126.   TempItemSize : word;
  127. begin
  128.   if Index >= MaxItems then
  129.     RunError(201);
  130.  
  131.   { compute index into memory }
  132.   Index := Index * ItemSize;
  133.   { determine the starting selector to access }
  134.   Sel := (Index div SegSize) * SelectorInc + MemStart;
  135.   { determine the offset into that selector }
  136.   Off := Index mod SegSize;
  137.  
  138.   if (SegSize - Off) < ItemSize then begin
  139.     TempItemSize := SegSize - Off;
  140.     FinishIt := true;
  141.   end
  142.   else begin
  143.     TempItemSize := ItemSize;
  144.     FinishIt := false;
  145.   end;
  146.  
  147.   { lock the memory - this only applies to windows }
  148.   GlobalLock(Sel);
  149.  
  150.   { get the pointer value }
  151.   P := ptr(Sel, Off);
  152.  
  153.   { move the data from memory to the field }
  154.   Move(P^, Item, TempItemSize);
  155.  
  156.   { unlock the memory - this only applies to windows }
  157.   GlobalUnLock(Sel);
  158.  
  159.   if FinishIt then begin
  160.     Sel := Sel + SelectorInc;
  161.     Off := 0;
  162.     { lock the memory - this only applies to windows }
  163.     GlobalLock(Sel);
  164.  
  165.     { get the pointer value }
  166.     P := ptr(Sel, Off);
  167.  
  168.     { move the data into memory }
  169.     Move(Item, P^, TempItemSize);
  170.  
  171.     { unlock the memory - this only applies to windows }
  172.     GlobalUnLock(Sel);
  173.   end;
  174.  
  175.   dec(MemOffset, ItemSize);
  176. end;
  177.  
  178. procedure TBigArray.Resize(NoItems : longint);
  179. { With a call to GlobalReAlloc() we can resize the array with out
  180.   loosing any data.  Here we also reinitialize the fields }
  181. var
  182.   TempMem : THandle;
  183. begin
  184.  
  185.   MaxItems := NoItems;
  186.   { compute new memory size }
  187.   MemSize := MaxItems * ItemSize;
  188.   { resize the memory allocated }
  189.   TempMem := GlobalReAlloc(MemStart, MemSize, gmem_Moveable);
  190.   { any errors? }
  191.   if TempMem = 0 then
  192.     RunError(203);
  193.  
  194.   MemStart := TempMem;
  195. end;
  196.  
  197. function TBigArray.GetMemSize : longint;
  198. { returns the current number of bytes allocated for the array }
  199. begin
  200.   GetMemSize := MemSize;
  201. end;
  202.  
  203. end.
  204.  
  205. {------------------------    DEMO PROGRAM  --------------------- }
  206.  
  207. program TestBigArray;
  208.  
  209. {$ifdef Windows}
  210. uses WinDos, WinCrt, WinTypes, WinProcs, BigArray;
  211. {$else}
  212. uses Dos, Crt, WinAPI, BigArray;
  213. {$endif}
  214.  
  215. const
  216.   elnum = 2000;
  217. type
  218.   TRec = record
  219.     i : integer;
  220.     r : real;
  221.     s : string;
  222.     a : array[0..3000] of char;
  223.   end;
  224.  
  225. var
  226.   Rec : TRec;
  227.   BArray : PBigArray;
  228.   X : longint;
  229. begin
  230.  
  231.   clrscr;
  232.  
  233.   writeln('memory available = ', memavail);
  234.  
  235.   new(BArray, Init(elnum, SizeOf(TRec)));
  236.  
  237.   for x := 0 to elnum-1 do begin
  238.     Rec.i := x;
  239.     BArray^.PutData(Rec, x);
  240.   end;
  241.  
  242.   for x := elnum-1 downto 0 do begin
  243.     BArray^.GetData(Rec, x);
  244.     if x <> Rec.i then
  245.       writeln(Rec.i);
  246.   end;
  247.  
  248.   writeln('first size of mem for array = ', BArray^.GetMemSize);
  249.  
  250. {  BArray^.Resize(20000);
  251.  
  252.   for x := 10000 to 19999 do begin
  253.     Rec.i := x;
  254.     BArray^.PutData(Rec, x);
  255.   end;
  256.  
  257.   for x := 19999 downto 0 do begin
  258.     BArray^.GetData(Rec, x);
  259.     writeln(Rec.i);
  260.   end;
  261.  
  262.   writeln('second size of mem for array = ', BArray^.GetMemSize);
  263. }
  264.   dispose(BArray, Done);
  265.   readln;
  266. end.
  267.